package cn.bs.busuo.account.service.impl;

import cn.bs.busuo.account.pojo.cachevo.CacheUserStandardVO;
import cn.bs.busuo.account.pojo.entity.*;
import cn.bs.busuo.account.pojo.param.SetAdminParam;
import cn.bs.busuo.account.pojo.vo.*;
import cn.bs.busuo.common.enumerator.ServiceCode;
import cn.bs.busuo.common.ex.ServiceException;
import cn.bs.busuo.common.pojo.po.UserStatePO;
import cn.bs.busuo.account.dao.cache.IUserCacheRepository;
import cn.bs.busuo.account.dao.persist.repository.IUserRepository;
import cn.bs.busuo.account.pojo.param.UserAddNewParam;
import cn.bs.busuo.account.pojo.param.UserBasicUpdateParam;
import cn.bs.busuo.account.service.IUserService;
import cn.bs.busuo.common.pojo.vo.PageData;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static cn.bs.busuo.common.consts.data.CommonConsts.*;

@Slf4j

@Service
public class UserServiceImpl implements IUserService {

    @Value("${busuo.dao.default-query-page-size}")
    private Integer defaultQueryPageSize;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IUserRepository userRepository;
    @Autowired
    private IUserCacheRepository userCacheRepository;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public void addNew(UserAddNewParam userAddNewParam) {

        // 检查用户名是否被占用
        String username = userAddNewParam.getUsername();
        int count = userRepository.countByUsername(username);
        if (count > 0) {
           String message = "添加用户失败，用户名已经被占用！";
           throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        User user = new User();
        BeanUtils.copyProperties(userAddNewParam, user);
        user.setEnable(1);
        String rawPassword = user.getPassword();
        String encodedPassword = passwordEncoder.encode(rawPassword);
        user.setPassword(encodedPassword);

        addNew1(user);
    }


//    @Override
//    public void delete(Long id) {
//        //无法删除系统管理员
//        if (id == 1) {
//            String message = "删除用户失败，尝试访问的数据不存在！";
//            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
//        }
//        //判断用户是否存在
//        Object queryResult = userRepository.getStandardById(id);
//        if (queryResult == null) {
//            String message = "删除用户失败，尝试访问的数据不存在！";
//            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
//        }
//        deleteById1(id);
//
//        // 你还应该删除此用户关联的其它数据，例如：文章、评论、购物车、订单等
//
//    }

    @Override
    public void updateInfo(Long userId, UserBasicUpdateParam userBasicUpdateParam) {
        //第一次删除缓存
        boolean b = userCacheRepository.deleteUserBase(userId);
        if (b) {
            System.out.println("第一次删除缓存成功");
        }else {
            System.out.println("第一次删除缓存失败");
        }
        //插入数据到数据库
        User user = new User();
        user.setId(userId);
        BeanUtils.copyProperties(userBasicUpdateParam, user);
        int rows = userRepository.updateById(user);
        if (rows != 1) {
            String message = "数据库修改基本信息失败，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
        System.out.println("更新数据库成功");
        //第二次异步删除缓存,保证最终一致性
        Message<Long> message = MessageBuilder.withPayload(userId).build();
        rocketMQTemplate.asyncSend("information-update", message, new SendCallback() {
            //异步线程接收反馈 消息发送成功
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("消息发送成功");
            }
            //异步线程发送失败 编写重试机制
            @Override
            public void onException(Throwable throwable) {
            throw new ServiceException(ServiceCode.ERROR_UPDATE,"用户信息更新的消息发送失败");
            }
        });
    }

    @Override
    public void updatePassword(Long id, String newPassword) {
        String oldPassword = userRepository.selectUserPasswordById(id);
        if (oldPassword == null) {
            String message = "修改密码失败，此用户不存在";
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
        boolean matches = passwordEncoder.matches(oldPassword, newPassword);
        if (matches){
            String message = "修改密码失败，新密码不能与旧密码相同！";
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
        String encodedPassword = passwordEncoder.encode(newPassword);
        User user = new User();
        user.setId(id);
        user.setPassword(encodedPassword);
        int rows = userRepository.updatePassword(user);
        if (rows != 1) {
            String message = "修改密码失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
        userCacheRepository.deleteUserState(id);

    }

    @Override
    public void setEnable(Long userId) {
        updateEnableById(userId, ENABLE_STATE_ON);
        userCacheRepository.setUserEnable(userId);
    }
    @Override
    public void setDisable(Long userId) {
        updateEnableById(userId, ENABLE_STATE_OFF);
        userCacheRepository.setUserDisabled(userId);
    }

    @Override
    public CacheUserStandardVO getStandardById(Long id) {
        //先去缓存获取数据
        CacheUserStandardVO userStandardVO = userCacheRepository.getStandardById(id);
        if (userStandardVO!= null) {
            return userStandardVO;
        }
        //AQS锁限制对数据库的访问
        Lock lock = new ReentrantLock();
        if(lock.tryLock()){
            //数据库查询
            UserStandardVO currentUser = userRepository.getStandardById(id);
            if (currentUser == null) {
                String message = "获取用户详情失败，尝试访问的用户数据不存在！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
            }
            CacheUserStandardVO cacheUserStandardVO = new CacheUserStandardVO();
            BeanUtils.copyProperties(currentUser, cacheUserStandardVO);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String lastLogin = sdf2.format(currentUser.getGmtLastLogin());
            cacheUserStandardVO.setGmtLastLogin(lastLogin);
            //存入缓存
            userCacheRepository.saveUserInformation(id, cacheUserStandardVO);
            return cacheUserStandardVO;
        }else {
            throw new ServiceException(ServiceCode.ERROR_UNKNOWN,"服务器忙,请稍后再试");
        }

    }
    @Override
    public PageData<CacheUserStandardVO> list(Integer pageNum) {
        return userCacheRepository.list(pageNum,defaultQueryPageSize);
    }

    @Override
    public PageData<CacheUserStandardVO> list(Integer pageNum, Integer pageSize) {
        return userCacheRepository.list(pageNum, pageSize);
    }

    @Override
    public void setAdmin(SetAdminParam setAdminParam) {
        int ifUserExits = userRepository.ifUserExits(setAdminParam.getUserId());
        if (ifUserExits!= 1) {
            String message = "添加权限失败，该用户不存在！";
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        int userRoleCount = userRepository.selectUserRoleIfExits(setAdminParam);
        if (userRoleCount != 0) {
            String message = "添加权限失败，该用户已经具有此权限！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        UserRole userRole = new UserRole();
        BeanUtils.copyProperties(setAdminParam, userRole);
        int ifSuccess = userRepository.setUserRole(userRole);
        if (ifSuccess!= 1) {
            String message = "添加权限失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
        userCacheRepository.deleteUserState(setAdminParam.getUserId());
    }

    @Override
    public void deleteAdmin(SetAdminParam setAdminParam) {
        int ifUserExits = userRepository.ifUserExits(setAdminParam.getUserId());
        if (ifUserExits!= 1) {
            String message = "添加权限失败，该用户不存在！";
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        int userRoleCount = userRepository.selectUserRoleIfExits(setAdminParam);
        if (userRoleCount != 1) {
            String message = "删除权限失败，该用户没有此权限！";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        int ifSuccess = userRepository.deleteUserRole(setAdminParam);
        if (ifSuccess!= 1) {
            String message = "删除权限失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
        userCacheRepository.deleteUserState(setAdminParam.getUserId());
    }

    @Override
    public List<AdminUserVO> adminList() {
        //直接从数据库查,懒得写了
        return userRepository.adminList();
    }

    @Transactional
    public void addNew1(User user) {
        int rows = userRepository.insert(user);
        //添加用户是否成功
        if (rows != 1) {
            String message = "添加用户失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
        UserRole userRole = new UserRole();
        userRole.setRoleId(10L);
        userRole.setUserId(userRepository.selectIdByUsername(user.getUsername()));
        int i = userRepository.newUserRole(userRole);
        //添加新用户角色是否成功
        if (i < 1) {
            String message = "添加用户失败，服务器忙，请稍后再尝试！";//用户角色添加失败
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_INSERT, message);
        }
    }
//    @Transactional
//    public void deleteById1(Long id){
//        int i = userRepository.deleteById1(id);
//        //删除用户角色是否成功
//        if (i != 1) {
//            String message = "删除用户失败，服务器忙，请稍后再尝试(user_role)！";
//            log.warn(message);
//            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
//        }
//        int rows = userRepository.deleteById(id);
//        //删除用户是否成功
//        if (rows != 1) {
//            String message = "删除用户失败，服务器忙，请稍后再尝试(user)！";
//            log.warn(message);
//            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
//        }
//        //删除用户缓存是否成功
//        boolean b = userCacheRepository.deleteUserState(id);
//        if (!b) {
//            String message = "删除用户失败，服务器忙，请稍后再尝试(redis)！";
//            throw new ServiceException(ServiceCode.ERROR_DELETE, message);
//        }
//    }
    /**
     * 修改用户的启用状态
     */
    private void updateEnableById(Long id, Integer enable) {
        //无法修改系统管理员的启用状态
        if (id == 1) {
            String message = ENABLE_STATE_TEXT[enable] + "用户失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        //查询用户是否存在
        UserStandardVO queryResult = userRepository.getStandardById(id);
        if (queryResult == null) {
            String message = ENABLE_STATE_TEXT[enable] + "用户失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        //判断用户是否处于当前状态
        if (queryResult.getEnable().equals(enable)) {
            String message = ENABLE_STATE_TEXT[enable] + "用户失败，当前用户已经处于"
                    + ENABLE_STATE_TEXT[enable] + "状态！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }

        User user = new User();
        user.setId(id);
        user.setEnable(enable);
        int rows = userRepository.updateById(user);
        //修改状态失败
        if (rows != 1) {
            String message = ENABLE_STATE_TEXT[enable] + "用户失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPDATE, message);
        }
        //修改状态成功,修改redis中的数据
        if (enable.equals(ENABLE_STATE_OFF)) {
            UserStatePO userState = userCacheRepository.getUserState(id);
            if (userState != null) {
                userCacheRepository.setUserDisabled(id);
            }
        }
    }
}